package smetana.modules.ui.form.search;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.apache.pivot.collections.FilteredList;
import org.apache.pivot.collections.List;
import org.apache.pivot.collections.Sequence;
import org.apache.pivot.util.Filter;
import org.apache.pivot.wtk.Action;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.ComponentKeyListener;
import org.apache.pivot.wtk.ComponentMouseButtonListener;
import org.apache.pivot.wtk.ComponentStateListener;
import org.apache.pivot.wtk.Keyboard.KeyLocation;
import org.apache.pivot.wtk.ListView;
import org.apache.pivot.wtk.ListViewSelectionListener.Adapter;
import org.apache.pivot.wtk.MessageType;
import org.apache.pivot.wtk.Mouse.Button;
import org.apache.pivot.wtk.Prompt;
import org.apache.pivot.wtk.PushButton;
import org.apache.pivot.wtk.Sheet;
import org.apache.pivot.wtk.SheetCloseListener;
import org.apache.pivot.wtk.Span;
import org.apache.pivot.wtk.TextInput;
import org.apache.pivot.wtk.TextInputTextListener;
import org.apache.pivot.wtk.content.ListViewItemRenderer;
import org.apache.pivot.wtkx.WTKX;
import smetana.modules.ui.form.AbstractPanel;
import smetana.util.Pivot;
import smetana.domain.IntId;

/**
 *
 * @author dmitry.mamonov
 */
public abstract class AbstractSearchPanel<T extends IntId> extends AbstractPanel {
    @WTKX
    TextInput textFilter;

    @WTKX
    ListView listView;

    FilteredList<T> filteredList = new FilteredList<T>();

    @WTKX
    PushButton buttonSelect;

    @WTKX
    PushButton buttonAdd;

    @WTKX
    PushButton buttonEdit;

    Action actionSelect = new Action(false) {
        @Override
        public void perform() {
            performSelect();
        }
    };

    Action actionAdd = new Action() {
        @Override
        public void perform() {
            final TextInput text = new TextInput();
            text.setText(textFilter.getText());
            text.selectAll();
            final Prompt prompt = new Prompt(
                    MessageType.QUESTION,
                    "Добавить запись:",
                    Pivot.<String>asList(),
                    text);
            text.getComponentKeyListeners().add(new ComponentKeyListener.Adapter() {
                @Override
                public boolean keyPressed(Component component, int keyCode, KeyLocation keyLocation) {
                    if (keyCode == java.awt.event.KeyEvent.VK_ENTER) {
                        prompt.close(true);
                        return true;
                    } else if (keyCode == java.awt.event.KeyEvent.VK_ESCAPE) {
                        prompt.close(false);
                        return true;
                    }
                    return false;
                }
            });
            prompt.getComponentStateListeners().add(new ComponentStateListener.Adapter() {
                @Override
                public void focusedChanged(Component component, Component obverseComponent) {
                    text.requestFocus();
                }
            });
            prompt.open(getComponent().getWindow(),
                    new SheetCloseListener() {
                        @Override
                        public void sheetClosed(Sheet sheet) {
                            System.out.println("result = " + sheet.getResult());
                            if (sheet.getResult() == true && text.getText().isEmpty() == false) {
                                System.out.println("text = " + text);
                                createNew(text.getText());
                                textFilter.setText(text.getText());
                                filteredList.setSource(load());
                                validateSelection(listView);
                            }
                        }
                    });

        }
    };

    Action actionEdit = new Action(false) {
        @Override
        public void perform() {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    };

    public AbstractSearchPanel() {
        super(AbstractSearchPanel.class);
    }

    @Override
    public void init() {
        wtkx.bind(this, AbstractSearchPanel.class);
        buttonSelect.setAction(actionSelect);
        buttonAdd.setAction(actionAdd);
        buttonEdit.setAction(actionEdit);

        textFilter.getComponentKeyListeners().add(new ComponentKeyListener.Adapter() {
            @Override
            public boolean keyPressed(Component component, int keyCode, KeyLocation keyLocation) {
                if (keyCode == java.awt.event.KeyEvent.VK_DOWN) {
                    if (listView.getListData().getLength() > 0) {
                        listView.setSelectedIndex(0);
                    }
                    listView.requestFocus();
                    return true;
                } else if (keyCode == java.awt.event.KeyEvent.VK_ENTER) {
                    if (listView.getListData().getLength() == 0) {
                        actionAdd.perform();
                    } else if (listView.getListData().getLength() == 1) {
                        listView.setSelectedIndex(0);
                        performSelect();
                    }
                    return true;
                }
                return false;
            }
        });

        filteredList.setSource(load());
        listView.setListData(filteredList);
        listView.getListViewSelectionListeners().add(new ValidateSelectionListener());
        listView.getComponentMouseButtonListeners().add(new ComponentMouseButtonListener.Adapter() {
            @Override
            public boolean mouseClick(Component component, Button button, int x, int y, int count) {
                if (button == Button.LEFT && count == 2 && listView.getSelectedIndex() >= 0) {
                    performSelect();
                    return true;
                }
                return false;
            }
        });
        listView.setItemRenderer(new ListViewItemRenderer(){
            @Override
            public void render(Object item, int index, ListView listView, boolean selected, boolean checked, boolean highlighted, boolean disabled) {
                String strItem = item==null?null:AbstractSearchPanel.this.toString((T)item);
                super.render(strItem, index, listView, selected, checked, highlighted, disabled);
            }
        });

        textFilter.getTextInputTextListeners().add(new TextInputTextListener() {
            @Override
            public void textChanged(final TextInput textInput) {
                filteredList.setFilter(new Filter<T>() {
                    java.util.List<String> filters = Lists.newArrayList(Splitter.on(" ").omitEmptyStrings().split(textInput.getText()));

                    @Override
                    public boolean include(T item) {
                        for (String filter : filters) {
                            if (AbstractSearchPanel.this.toString(item).toLowerCase().contains(filter.toLowerCase()) == false) {
                                return false;
                            }
                        }
                        return true;
                    }
                });
                validateSelection(listView);
            }
        });

    }

    protected abstract T createNew(String text);

    protected abstract void edit(T current, String newText);

    protected abstract List<T> load();

    protected abstract String toString(T value);

    protected abstract void performSelect();

    private void validateSelection(ListView listView) {
        if (listView.getSelectedIndex() < 0) {
            if (listView.getListData().getLength() == 1) {
                listView.setSelectedIndex(0);
            }
        }
        boolean someRowSelected = listView.getSelectedIndex() >= 0;
        actionSelect.setEnabled(someRowSelected);
        actionEdit.setEnabled(someRowSelected);
    }

    public T getResult() {
        return (T) listView.getSelectedItem();
    }

    private class ValidateSelectionListener extends Adapter {
        @Override
        public void selectedRangeAdded(ListView listView, int rangeStart, int rangeEnd) {
            validateSelection(listView);
        }

        @Override
        public void selectedRangeRemoved(ListView listView, int rangeStart, int rangeEnd) {
            validateSelection(listView);
        }

        @Override
        public void selectedRangesChanged(ListView listView, Sequence<Span> previousSelectedRanges) {
            validateSelection(listView);
        }
    }
}
